#include "Float.h"

Float::Float(int precision, long double value) {
	_precision = precision;
	_mant = "";
	longDoubleToBinary(value);
	_value = binaryToLongDouble();
}

Float::~Float() {
}

/**
* Calcula la mantisa y el exponente del numero que figura en value.
*/
void Float::longDoubleToBinary(long double value) {
	int sizeMantisa = _precision;
	long double x, mant;
	x = value;
	if (x < 0) { 
		x = ((-1) * value);
	} 
	_neg = (value < 0);
	int exp = 0;
	// Ahora se busca la mantisa
	mant = x;
	while (mant >= 1) {
		mant /= 2;
        	exp++;
        // en este punto x = mant * 2^(exp)
	}

	while (mant < 0.5 && mant != 0) {
		mant *= 2;
        	exp--;
	}

	_exp = exp;
	while (mant > 0 && sizeMantisa > 0) {
		mant *= 2;
        	if (mant >= 1) {
			_mant += "1";
			mant -= 1;
        	} else {
			_mant += "0";
		}
		sizeMantisa--;
    	}
	while (sizeMantisa > 0) {
		_mant += "0";
		sizeMantisa--;
	}
}

Float Float::operator+(Float ob1) {
	long double result = _value + ob1.getValue();
	return Float(_precision, result);
}

Float Float::operator-(Float obj) {
	long double result = _value - obj.getValue();
	return Float(_precision, result);
}

Float Float::operator/(Float obj) {
	long double result = _value / obj.getValue();
	return Float(_precision, result);
}

Float& Float::operator=(const Float& obj) {
	if (this == &obj) 
		return *this;
	_precision = obj.getPrecision();
	_value = obj.getValue();
	_exp = obj.getExp();
	_mant = obj.getMant();
	return *this;
}

Float Float::operator*(Float obj) {
	long double result = _value * obj.getValue();
	return Float(_precision, result);
}

int operator== (const Float& a, const Float& b){
	if (a.getValue()==b.getValue())
		return 1;
	else
		return 0;
}

int operator!= (const Float& a, const Float& b){
	if (a.getValue() != b.getValue())
		return 1;
	else
		return 0;
}

const int Float::getPrecision() const {
	return _precision;
}

const long double Float::getValue() const {
	return _value;
}

const int Float::getExp() const {
	return _exp;
}

const string Float::getMant() const{
	return _mant;
}

long double Float::binaryToLongDouble() {
	long double result, suma = 0;
	result = pow((double)2,(double)_exp);
	string bit;
	for(int i=0; i<_mant.size(); i++) {
		bit = _mant[i];
		suma += (atoi(bit.c_str()) * pow((double)2,(double)(-i-1)));
	}
	if (_neg) {
		return (-1)*(result * suma);
	}
	return (result * suma);
	
}

string const Float::getSigno() const {
	return (_neg ? "negativo" : "positivo");
}

ostream &operator<<(ostream &stream, Float &ob)
{
  stream << "signo: " << ob.getSigno() << endl;
  stream << "valor decimal: " << ob.getValue() << endl;
  //para graficos en excel
  //stream << ob.getValue();
  stream << "exp: " << ob.getExp() << endl;
  stream << "mantisa : "  << ob.getMant() << endl;
  return stream;
}
